#include <kernel.h>

void
print_backtrace(uint32_t ebp, uint32_t eip)
{
     struct eipdebuginfo_s debug_info;
	 if (ebp == 0 && eip == 0)
	 {
		  __asm__ __volatile__("movl %%ebp, %0" : "=r" (ebp));
		  if (ebp == 0)
		  {
			   ekf_cprintf("Stack backtrace is empty(optimized?)\n");
			   return;
		  }
		  eip = *((uint32_t *)(ebp) + 1);
		  ebp = *(uint32_t *)(ebp);
	 }

     ekf_cprintf("Stack backtrace:\n");
     /* ekf_cprintf("  ebp: %p\n", ebp); */

	 uint32_t lines = 0;
     while (1)
     {
		  /* break if the ptr down to user mode */
		  if (ebp < KSHARE)
		  {
			   break;
		  }
          
		  ekf_cprintf("  ebp: %p  eip: %p", ebp, eip);
          
		  if (debuginfo_eip(eip, &debug_info) >= 0)
		  {
			   ekf_cprintf("  args[%d]", debug_info.eip_fn_narg);
			   int arg_idx;
			   uint32_t arg;
			   for (arg_idx = 0; arg_idx < debug_info.eip_fn_narg; ++ arg_idx)
			   {
					arg = *((uint32_t *)ebp + arg_idx + 2);
					ekf_cprintf(" %08x", arg);
			   }

			   ekf_cprintf("\n\t%s:%d: ", debug_info.eip_file, debug_info.eip_line, debug_info.eip_fn_narg);
               
			   int i;
			   for (i = 0; i != debug_info.eip_fn_namelen; ++i)
					ekf_cputchar(debug_info.eip_fn_name[i]);

			   ekf_cprintf("+%d\n", eip - debug_info.eip_fn_addr);
		  }
		  else
		  {
			   // ekf_cprintf("%s : %d\n", debug_info.eip_file, debug_info.eip_line);
			   ekf_cprintf(" [debug info missing]\n");
		  }

#if 0
		  if (++ lines == 5)
		  {
			   lines = 0;
			   ekf_cprintf("Enter to show next 5 items\n");
			   ekf_readline(NULL);
		  }
#endif

		  eip = *((uint32_t *)(ebp) + 1);
		  ebp = *(uint32_t *)(ebp);
     }
}
